package service

import (
	"github.com/wonderivan/logger"
	"teresa/dao"
	"teresa/model"
)

var Workflow workflow

type workflow struct{}

// 定义workflowCreate的类型
type WorkflowCreate struct {
	Name      string            `json:"name"`
	Namespace string            `json:"namespace"`
	Replicas  int32             `json:"replicas"`
	Image     string            `json:"image"`
	Command   []string          `json:"command"`
	Label     map[string]string `json:"label"`
	Cpu       string            `json:"cpu"`
	Memory    string            `json:"memory"`
	// containerport与下面的targetport保持一致，因此这里不写，下面直接传target_port的值
	//	ContainerPort 	int32					`json:"container_port"`
	HealthCheck      bool                   `json:"health_check"`
	HealthPath       string                 `json:"health_path"`
	Type             string                 `json:"type"`
	TargetPort       int32                  `json:"target_port"`
	Port             int32                  `json:"port"`
	NodePort         int32                  `json:"node_port"`
	ServiceMetaLabel map[string]string      `json:"servicemetalabel"`
	Hosts            map[string][]*HttpPath `json:"hosts"`
}

// 获取分页查询,这里利用mysql数据库自己的分页功能实现。
func (w *workflow) GetList(name, namespace string, page, limit int) (data *dao.WorkflowResp, err error) {
	data, err = dao.Workflow.GetWorkflows(name, namespace, limit, page)
	if err != nil {
		return nil, err
	}
	return data, nil
}

// 查询workflow单条数据
func (w *workflow) GetWorkflowById(id int) (data *model.Workflow, err error) {
	data, err = dao.Workflow.GetWorkflowById(id)
	if err != nil {
		return nil, err
	}
	return data, nil
}

// 创建workflow
func (w *workflow) CreateWorkflow(data *WorkflowCreate) (err error) {
	//定义ingress名字以及判断ingress类型
	var ingressName string
	if data.Type == "Ingress" {
		ingressName = getIngressName(data.Name)
	} else {
		ingressName = ""
	}

	// 这里先落库，然后创建资源。最好是有事务性，创建资源失败，回退步骤
	// workflow数据落库
	workflow := &model.Workflow{
		Name:       data.Name,
		Namespace:  data.Namespace,
		Replicas:   data.Replicas,
		Deployment: data.Name,
		Service:    getServiceName(data.Name),
		Ingress:    ingressName,
		Type:       data.Type,
	}
	err = dao.Workflow.CreateWorkflow(workflow)
	if err != nil {
		return err
	}
	// 创建k8s资源
	err = createWorkflowRes(data)
	if err != nil {
		return err
	}

	return nil
}

// 删除workflow
func (w *workflow) DelWorkflowById(id int) (err error) {
	//获取数据库数据
	workflowid, err := dao.Workflow.GetWorkflowById(id)
	if err != nil {
		return err
	}
	// 删除k8s资源
	err = delWorkflowRes(workflowid)
	if err != nil {
		return err
	}
	// 删除数据库数据
	err = dao.Workflow.DelWorkflowById(id)
	if err != nil {
		return err
	}
	return nil
}

// 创建k8s资源deployment  service  ingress
func createWorkflowRes(data *WorkflowCreate) (err error) {
	// 创建deloyment
	dc := &DeployCreate{
		Name:          data.Name,
		Namespace:     data.Namespace,
		Replicas:      data.Replicas,
		Image:         data.Image,
		Command:       data.Command,
		Label:         data.Label,
		Cpu:           data.Cpu,
		Memory:        data.Memory,
		ContainerPort: data.TargetPort,
		HealthCheck:   data.HealthCheck,
		HealthPath:    data.HealthPath,
	}
	// 包内调用，直接写方法名即可
	err = Deploy.CreateDeployment(dc)
	if err != nil {
		return err
	}

	var serviceType string
	if data.Type != "Ingress" {
		serviceType = data.Type
	} else {
		serviceType = "ClusterIP"
	}
	// 创建service
	sc := &ServiceCreate{
		Name:       getServiceName(data.Name),
		Namespace:  data.Namespace,
		Type:       serviceType,
		TargetPort: data.TargetPort,
		//Port:       data.TargetPort,
		NodePort:   data.NodePort,
		// ServicePodLabel，因为共用data.Label的值
		ServicePodLabel: data.Label,
		// ServiceMetaLabel是service自己独有的label，因此这里单独提供，可与servicepodlabel保持一致
		//ServiceMetaLabel: data.ServiceMetaLabel,
	}
	if err := Servicev1.CreateService(sc); err != nil {
		return err
	}

	// 创建ingress，1.20版本可用
	var ings *IngressCreate
	if data.Type == "Ingress" {
		ings = &IngressCreate{
			Name:      getIngressName(data.Name),
			Namespace: data.Namespace,
			Hosts:     data.Hosts,
		}
	}
	if err := Ingress.CreateIngress(ings); err != nil {
		return err
	}
	return nil
}

// 删除k8s资源deployment  service  ingress
func delWorkflowRes(workflow *model.Workflow) (err error) {
	logger.Info("开始删除workflow对应的deployment")
	err = Deploy.DeleteDeployment(workflow.Name, workflow.Namespace)
	if err != nil {
		return err
	}
	logger.Info("删除成功")
	logger.Info("开始删除workflow对应的service")
	err = Servicev1.DeleteService(workflow.Namespace, getServiceName(workflow.Name))
	// 删除失败应该打印出来日志，不建议return出去，否则执行不下去
	if err != nil {
		return err
	}
	logger.Info("删除成功")
	logger.Info("开始删除workflow对应的ingress")
	if workflow.Type == "Ingress" {
		err = Ingress.DeleteIngress(workflow.Namespace, getIngressName(workflow.Name))
		if err != nil {
			return err
		}
	}
	logger.Info("删除成功")
	return nil
}

// 与ingress.go文件的getServiceNameSvc一样的用法
func getServiceName(workflowName string) (serviceName string) {
	return workflowName + "-svc"
}

func getIngressName(workflowName string) (ingressName string) {
	return workflowName + "-ing"
}
